package com.geekgo.flowcontroller.support;

import com.geekgo.flowcontroller.FlowControllerContext;
import com.geekgo.flowcontroller.FlowControllerInterceptor;
import com.geekgo.flowcontroller.annotation.RateLimit;
import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author geekgo
 * @version 2016/8/5 11:49
 */
public class ConfigurationContext implements BeanDefinitionRegistryPostProcessor,InitializingBean {

    private static final Logger LOGGER = LogManager.getLogger(ConfigurationContext.class);
    private FlowControllerContext context = new FlowControllerContext();
    private FlowControllerInterceptor interceptor = new FlowControllerInterceptor(context);
    private String scanPackages;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        AnnotationBeanScanner scanner = new AnnotationBeanScanner(beanDefinitionRegistry, RateLimit.class) {
            @Override
            void onClassFound(GenericBeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
                Class<?> targetClass = beanDefinition.getBeanClass();
                context.addRateLimiters(targetClass);
                beanDefinition.setBeanClass(ProxyFactoryBean.class);
                beanDefinition.getPropertyValues().add("targetType",targetClass);
                beanDefinition.getPropertyValues().add("interceptor",interceptor);
            }
        };
        scanner.doScan(org.springframework.util.StringUtils.tokenizeToStringArray(this.scanPackages.trim(), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        //do nothing
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Preconditions.checkState(StringUtils.isNotEmpty(scanPackages),"scanPackage can't be empty");
    }

    public String getScanPackages() {
        return scanPackages;
    }

    public void setScanPackages(String scanPackages) {
        this.scanPackages = scanPackages;
    }
}
